﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Bymed.SpineScan.DataModel;
using Bymed.SpineScan.Repository.Interface;
using Bymed.SpineScan.Service.Interface;
using Bymed.SpineScan.Service.Shared;
using Bymed.SpineScan.Service.Validation;

namespace Bymed.SpineScan.Service
{
    public class CustomizedTestItemService : ServiceBase<CustomizedTestItem>, ICustomizedTestItemService
    {
        public CustomizedTestItemService(IRepositoryFactory repositoryFactory) : base(repositoryFactory, new CustomizedTestItemValidator()) { }

        /// <summary>
        /// Synchronize the input DiagnosticMessageReference list with data source.
        /// Add new DiagnosticMessageReference. Update existing DiagnosticMessageReference. Delete removed DiagnosticMessageReference.
        /// </summary>
        /// <param name="entities">The input DiagnosticMessageReference list.</param>
        public void Synchronize(IList<CustomizedTestItem> entities)
        {
            using (RepositoryFactory)
            {
                RepositoryFactory.OpenSessionWithTransaction();
                var customizedTestItemRepository = RepositoryFactory.CreateCustomizedTestItemRepository();
                var testTrackingRepository = RepositoryFactory.CreateTestTrackingRepository();
                var testResultRepository = RepositoryFactory.CreateTestResultRepository();
                var entityCount = entities.Count();

                for (int i = 0; i < entityCount; i++)
                {
                    if (string.IsNullOrEmpty(entities[i].ItemTimestamp))
                    {
                        entities[i].ItemTimestamp = GeneralUtility.GetTimestamp();
                    }

                    entities[i].OrderIndex = i + 1;
                    customizedTestItemRepository.AddOrUpdate(entities[i]);
                }

                // Get all CustomizedTestItems that would be removed.
                var existingEntityIds = entities.Select(m => m.ItemTimestamp).ToList();
                var removedEntities = customizedTestItemRepository.Query(m => !existingEntityIds.Contains(m.ItemTimestamp));

                foreach (var item in removedEntities)
                {
                    // Get all related TestResults.
                    var removedTestResults = testResultRepository.Query(p => p.TestItemName == item.ItemTimestamp);

                    // Delete all related TestResults.
                    testResultRepository.Delete(removedTestResults);

                    // Get all TestTrackings which ONLY contains this CustomizedTestItem.
                    var removedTestTrackings = testTrackingRepository.Query(p => p.TestResults.Any(t => t.TestItemName == item.ItemTimestamp) && p.TestResults.Count == 1);

                    // Delete the TestTrackings which only contains this CustomizedTestItem.
                    foreach (var testTracking in removedTestTrackings)
                    {
                        CommonService.DeleteTestTracking(RepositoryFactory, testTracking);
                    }
                }

                customizedTestItemRepository.Delete(removedEntities);
                RepositoryFactory.Commit();
            }
        }
    }
}
